﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using V2TEK.NET.SH.Silverlight.Charts.Core.Schedule;
using System.Collections.Specialized;
using System.ComponentModel;
using V2TEK.NET.SH.Silverlight.Charts.Core;
using System.Linq;

namespace V2TEK.NET.SH.Silverlight.Charts.GanttHelper
{
    public class AbstractTaskDescriptor : DependencyObject, ITaskDescriptor, INotifyPropertyChanged
    {

        private string _wbs;
        private TaskType _taskType;
        public const string TASKTYPE = "TASKTYPE";

        public const string STARTDATE_PROPERTY = "STATEDATE";
        public const string ENDDATE_PROPERTY = "ENDDATE";
        public const string TASKNAME_PROPERTY = "TASKNAME";
        public const string TASKTYPE_PROPERTY = "TASKTYPE";
        public const string RESOURCE_PROPERTY = "RESOURCE";
        public const string COMPLETE_PERCENT_PROPERTY = "COMPLETE_PERCENT";
        public const string CONSTRAINTS_PROPERTY = "ConstraintString";
        public const string WBS_PROPERTY = "WBS";
        public const string TOTALMILLISECONDS_PROPERTY = "TotalMilliseconds";

        private bool _isSelected;
        private bool _isExpand;

        private int _totalCount = 0;
        private int _level = 0;
        private int _totalCountExClps;
        private object _uniqueId = null;

        public event EventHandler<NotifyChildrenCollectionChangeArgs> ChildrenCollectionSet;

        public AbstractTaskDescriptor()
        {
            this.Children = new ObservableCollection<ITaskDescriptor>();
        }

        private void RaiseChildrenCollectionSet(NotifyChildrenCollectionChangeArgs args)
        {
            foreach (ITaskDescriptor task in args.NewChildren)
            {
                UpdateTaskInChildren(task);
            }

            if (ChildrenCollectionSet != null)
                ChildrenCollectionSet(this, args);
        }

        private void UpdateTaskInChildren(ITaskDescriptor task)
        {
            //task.Level = this.Level + 1;
            task.Parent = this;
        }

        void Children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {

                case NotifyCollectionChangedAction.Add:
                    ITaskDescriptor task = this.Children[e.NewStartingIndex];
                    UpdateTaskInChildren(task);
                    break;
                case NotifyCollectionChangedAction.Remove:
                case NotifyCollectionChangedAction.Replace:
                    throw new NotImplementedException("在AbstractTaskDescriptor Line53,没有实现Replace");
                    break;
                case NotifyCollectionChangedAction.Reset:

                    break;
            }

            CalculateTotalCount();
            CalculateTotalCountExClps();
        }

        #region unuse


        ///// <summary>
        ///// 必须与结构一致
        ///// </summary>
        //public ObservableCollection<int> InternalCode
        //{
        //    get
        //    {
        //        return _internalCode;
        //    }
        //}

        #endregion

        #region ITaskDescriptor Members

        public object UniqueId
        {
            get
            {
                if (_uniqueId == null)
                    this._uniqueId = Guid.NewGuid();

                return _uniqueId;
            }
            set
            {
                _uniqueId = value;
            }
        }

        public bool IsExpand
        {
            get { return _isExpand; }
            set
            {
                if (value != _isExpand)
                {
                    _isExpand = value;
                }
            }
        }

        public ITaskDescriptor Ghost { get; set; }

        public virtual string DisplayText
        {
            get { throw new NotImplementedException(); }
        }

        public virtual string Description
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public bool ReadOnly
        {
            get;
            set;
        }

        public virtual string Tooltip
        {
            get { throw new NotImplementedException(); }
        }

        #endregion

        #region ITime Members

        public virtual DateTime StartDate
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public virtual DateTime EndDate
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public virtual double TotalMilliseconds
        {
            //get { throw new NotImplementedException(); }
            //set
            //{
            //}
            get;
            set;
        }

        #endregion

        #region ICloneable<ITaskDescriptor> Members

        public virtual ITaskDescriptor Clone()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region ITask<ITaskDescriptor> Members

        public ITime TimeBaseLine
        {
            get;
            set;
        }

        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }
            set
            {
                if (value != _isSelected)
                {
                    _isSelected = value;
                }
            }
        }

        public string WBS
        {
            get
            {
                return _wbs;
            }
            set
            {
                _wbs = value;
            }
        }

        /// <summary>
        /// 低性能
        /// Low performance
        /// </summary>
        public int TotalCount
        {
            get
            {
                //if (TaskType != TaskType.Task && _totalCount > 0 && ReadOnly)
                //{
                //    return _totalCount;
                //}

                CalculateTotalCount();
                return _totalCount;
            }
        }

        private void CalculateTotalCount()
        {
            _totalCount = Children.Count;
            foreach (ITaskDescriptor des in Children)
            {
                _totalCount += des.TotalCount;
            }
        }

        public int TotalCountExClps
        {
            get
            {
                //if (TaskType != TaskType.Task && _totalCountExClps > 0 && ReadOnly)
                //{
                //    return _totalCountExClps;
                //}

                CalculateTotalCountExClps();
                return _totalCountExClps;
            }
        }

        private void CalculateTotalCountExClps()
        {
            _totalCountExClps = Children.Count;
            foreach (ITaskDescriptor des in Children)
            {
                if (des.IsExpand && des.EnableExpand)
                    _totalCountExClps += des.TotalCountExClps;
            }
        }

        public virtual string TaskName
        {
            get;
            set;
        }



        public virtual float PercentComplete
        {
            get { return (float)GetValue(PercentCompleteProperty); }
            set { SetValue(PercentCompleteProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PercentComplete.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PercentCompleteProperty =
            DependencyProperty.Register("PercentComplete", typeof(float), typeof(AbstractTaskDescriptor), new PropertyMetadata(0f, new PropertyChangedCallback(PercentCompleteChanged)));


        protected static void PercentCompleteChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is AbstractTaskDescriptor)
            {
                ((AbstractTaskDescriptor)d).PercentCompleteChanged(e.OldValue, e.NewValue);
            }
        }

        protected void PercentCompleteChanged(object oldValue, object newValue)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(COMPLETE_PERCENT_PROPERTY));
            }
        }

        //public virtual float PercentComplete
        //{
        //    get;
        //    set;
        //}


        public virtual DependencyDictionary<string, object> ExtendAttributes
        {
            get { return (DependencyDictionary<string, object>)GetValue(ExtendAttributesProperty); }
            set { SetValue(ExtendAttributesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ExtendAttributes.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ExtendAttributesProperty =
            DependencyProperty.Register("ExtendAttributes", typeof(DependencyDictionary<string, object>), typeof(AbstractTaskDescriptor), null);

        

        public virtual IResource Resource
        {
            get { return (IResource)GetValue(ResourceProperty); }
            set { SetValue(ResourceProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Resource.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ResourceProperty =
            DependencyProperty.Register("Resource", typeof(IResource), typeof(AbstractTaskDescriptor), new PropertyMetadata(new PropertyChangedCallback(ResourcePropertyChanged)));


        protected static void ResourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is AbstractTaskDescriptor)
            {
                ((AbstractTaskDescriptor)d).ResourcePropertyChanged(e.OldValue, e.NewValue);
            }
        }

        protected void ResourcePropertyChanged(object oldValue, object newValue)
        {
            if (mResources == null)
                mResources = new List<IResource>();

            mResources.Clear();

            IResource res = newValue as IResource;
            if (res.Code != null && res.DisplayName != null)
            {
                string[] codes = res.Code.Split(',');
                string[] names = res.DisplayName.Split(',');
                for (int i = 0; i < names.Length; i++)
                {
                    IResource r = new HumanResource();
                    if (codes.Length > i)
                    {
                        r.Code = codes[i];
                    }
                    r.DisplayName = names[i];
                    mResources.Add(r);
                }
            }
            if (PropertyChanged != null)
            {

                PropertyChanged(this, new PropertyChangedEventArgs(RESOURCE_PROPERTY));
            }
        }

        public virtual TaskType TaskType
        {
            get
            {
                if (_taskType == TaskType.None)
                {
                    if (Children.Count > 0)
                        _taskType = TaskType.SummaryTask;
                    else
                        _taskType = TaskType.Task;
                }
                return _taskType;
            }
            set
            {
                _taskType = value;
            }
        }

        private bool _enableExpand;
        public bool EnableExpand
        {
            get
            {
                return _enableExpand;
            }
            set
            {
                if (_enableExpand != value)
                {
                    _enableExpand = value;
                    if (_enableExpand)
                    {
                        this.Children.CollectionChanged += new NotifyCollectionChangedEventHandler(Children_CollectionChanged);
                    }
                    else
                    {
                        this.Children.CollectionChanged -= new NotifyCollectionChangedEventHandler(Children_CollectionChanged);
                    }
                }
            }
        }

        private List<IConstraint<ITaskDescriptor>> _constraints;
        public virtual List<IConstraint<ITaskDescriptor>> Constraints
        {
            get
            {
                if (_constraints == null)
                    _constraints = new List<IConstraint<ITaskDescriptor>>();
                return _constraints;
            }
        }


        public ITaskDescriptor Parent
        {
            get;
            set;
        }

        private ObservableCollection<ITaskDescriptor> _children;
        public ObservableCollection<ITaskDescriptor> Children
        {
            get
            {
                return _children;
            }
            set
            {
                RaiseChildrenCollectionSet(new NotifyChildrenCollectionChangeArgs { NewChildren = value, OldChildren = _children, Action = NotifyCollectionChangedAction.Replace });
                if (_children != null)
                    _children.CollectionChanged -= new NotifyCollectionChangedEventHandler(_children_CollectionChanged);
                _children = value;
                if (_children != null)
                    _children.CollectionChanged += new NotifyCollectionChangedEventHandler(_children_CollectionChanged);
            }
        }

        void _children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (var item in e.NewItems)
                    {
                        UpdateTaskInChildren(item as ITaskDescriptor);
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    foreach (var item in e.OldItems)
                    {
                        ((ITaskDescriptor)item).Parent = null;
                    }
                    break;
                case NotifyCollectionChangedAction.Replace:
                    foreach (var item in e.OldItems)
                    {
                        ((ITaskDescriptor)item).Parent = null;
                    }
                    foreach (var item in e.NewItems)
                    {
                        UpdateTaskInChildren(item as ITaskDescriptor);
                    }
                    break;
                case NotifyCollectionChangedAction.Reset:
                    break;
            }
        }

        public int Level
        {
            get
            {
                if (this.Parent != null)
                    return this.Parent.Level + 1;
                return 0;
                //return _level;
            }
            set
            {
                _level = value;
            }
        }

        #endregion

        #region IHierarchicalData<ITaskDescriptor> Members


        public object DataSource
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public ObservableCollection<ITaskDescriptor> RecurToList()
        {
            throw new NotImplementedException();
        }

        #endregion

        //public event EventHandler<CountChangeArgs> TotalCountChanged;
        //public event EventHandler<CountChangeArgs> TotalCountExClpsChanged;

        #region ITask Members


        private string _constraintString;
        public string ConstraintString
        {
            get
            {
                return _constraintString;
            }
            set
            {
                if (_constraintString != value)
                {
                    _constraintString = value;
                    if (PropertyChanged != null)
                        PropertyChanged(this, new PropertyChangedEventArgs(CONSTRAINTS_PROPERTY));
                }
            }
        }

        #endregion


        public bool HasStartDate
        {
            get;
            set;
        }

        public bool HasEndDate
        {
            get;
            set;
        }


        private List<IResource> mResources = null;
        public IEnumerable<IResource> Resources
        {
            get
            {
                if (mResources == null)
                    return null;
                return mResources.ToArray();
            }
        }
    }

    public class CountChangeArgs : EventArgs
    {
        public int DiffValue { get; set; }
    }
}
